#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define PORT 8889
#define BUFFER_SIZE 1024
#define CREDENTIALS_FILE "credentials.dat"
#define MAX_USERS 100

// 定义用户结构体
struct User {
    char username[20];
    char password[20];
};

// 保存多个用户信息到文件
void saveCredentials(struct User* users, int userCount) {
    FILE* fp = fopen(CREDENTIALS_FILE, "w");
    if (fp) {
        for (int i = 0; i < userCount; i++) {
            fprintf(fp, "%s %s\n", users[i].username, users[i].password);
        }
        fclose(fp);
    } else {
        perror("无法保存注册信息到文件");
    }
}

// 从文件加载多个用户信息
int loadCredentials(struct User* users) {
    FILE* fp = fopen(CREDENTIALS_FILE, "r");
    if (fp) {
        int count = 0;
        while (fscanf(fp, "%s %s", users[count].username, users[count].password) == 2) {
            count++;
            if (count >= MAX_USERS) {
                break;  // 防止超出数组界限
            }
        }
        fclose(fp);
        return count;
    } else {
        // 如果文件不存在或者读取失败，初始化数组
        for (int i = 0; i < MAX_USERS; i++) {
            strcpy(users[i].username, "");
            strcpy(users[i].password, "");
        }
        return 0;
    }
}

// 检查用户名是否已存在
int isUsernameExists(struct User* users, int userCount, const char* username) {
    for (int i = 0; i < userCount; i++) {
        if (strcmp(users[i].username, username) == 0) {
            return 1;
        }
    }
    return 0;
}

void send_command(int sockfd, const char* command) {
    send(sockfd, command, strlen(command), 0);
}

void receive_response(int sockfd, char* buffer, int buffer_size) {
    int bytes_read = read(sockfd, buffer, buffer_size - 1);
    if (bytes_read > 0) {
        buffer[bytes_read] = '\0';
        printf("Server: \n%s\n", buffer);
    } else {
        printf("服务器未响应.\n");
    }
}

void taozi() {
    int sockfd;
    struct sockaddr_in serv_addr;
    char buffer[BUFFER_SIZE] = {0};

    // 创建 socket
    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        perror("socket");
        exit(EXIT_FAILURE);
    }

    memset(&serv_addr, '0', sizeof(serv_addr));

    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(PORT);

    // 将 IPv4 地址从文本转换成二进制形式
    if (inet_pton(AF_INET, "192.168.10.188", &serv_addr.sin_addr) <= 0) {
        perror("IP 错误");
        exit(-1);
    }

    // 连接到服务器
    if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
        perror("connection");
        exit(-1);
    }

    // 发送命令并接收响应
    while (1) {
        system("clear");
        printf("-------------------- 欢 迎 进 行 学 生 信 息 操 作 -------------------------\n");
        //printf("Enter command (query+, add+<info>, update+<id>,<new_info>, delete+<id>, exit):\n");
        printf("(^_^)-------             query+1                 : 查看所有学生信息 --------\n");
        printf("(^_^)-------    add+<id,name,age,sex,score>      : 添加学生信息     --------\n");
        printf("(^_^)------- update+<id>,<id,name,age,sex,score> : 修改学生信息     --------\n");
        printf("(^_^)-------           delete+<id>               : 删除学生信息     --------\n");
        printf("(^_^)-------           input<exit>               : 退出学生信息操作 --------\n");
        printf("请根据上面提示输入你想实现功能的命令\u263A\n");
        printf("\n");
        printf(">>");
        fgets(buffer, BUFFER_SIZE, stdin);

        if (strncmp(buffer, "exit", 4) == 0) {
            break;
        }

        send_command(sockfd, buffer);
        receive_response(sockfd, buffer, BUFFER_SIZE);
        sleep(2);
    }

    // 关闭 socket
    close(sockfd);
}

void teachermenu() {
    system("clear");
    printf("--------- 欢迎进入学生管理系统 -------\n");
    printf("(^_^)---------- 1 登录 -------------\n");
    printf("(^_^)---------- 2 注册 -------------\n");
    printf("(^_^)---------- 3 退出 -------------\n");
    printf("请输入您的选择：");
}

int main() {
    struct User users[MAX_USERS];
    int userCount = loadCredentials(users);

    int repeatMenu = 1;
    int choice;

    while (repeatMenu) {
        teachermenu();
        scanf("%d", &choice);

        switch (choice) {
            case 1:
                printf("请输入您的名字：");
                char name[20];
                scanf("%s", name);
                // 清除输入缓冲区
                int c;
                while ((c = getchar())!= '\n' && c!= EOF);

                printf("请输入您的密码：");
                char password[20];
                scanf("%s", password);
                // 清除输入缓冲区
                while ((c = getchar())!= '\n' && c!= EOF);

                int found = 0;
                for (int i = 0; i < userCount; i++) {
                    if (strcmp(name, users[i].username) == 0 && strcmp(password, users[i].password) == 0) {
                        found = 1;
                        printf("登陆成功！\n");
                        sleep(2);
                        taozi();
                        break;
                    }
                }
                if (!found) {
                    printf("该用户未注册或名字输入错误或密码错误！\n");
                    sleep(2);
                    continue;
                }
                break;

            case 2:
                printf("请输入您的名字：");
                char newUsername[20];
                scanf("%s", newUsername);
                // 清除输入缓冲区
                int d;
                while ((d = getchar())!= '\n' && d!= EOF);

                // 检查用户名是否已存在
                if (isUsernameExists(users, userCount, newUsername)) {
                    printf("\n该用户已存在请重新注册！\n");
                    sleep(2);
                    continue;
                }

                printf("请输入您的密码：");
                char newPassword[20];
                scanf("%s", newPassword);
                // 清除输入缓冲区
                while ((d = getchar())!= '\n' && d!= EOF);

                strcpy(users[userCount].username, newUsername);
                strcpy(users[userCount].password, newPassword);
                userCount++;

                saveCredentials(users, userCount);
                printf("注册成功！\n");
                printf("即将返回菜单，可进行登录操作！\n");
                sleep(2);
                continue;

            case 3:
                repeatMenu = 0;
                break;
        }
    }

    return 0;
}